package com.uniflow.controller;

import com.uniflow.common.PageResult;
import com.uniflow.common.Result;
import com.uniflow.entity.ProcessDefinition;
import com.uniflow.entity.ProcessInstance;
import com.uniflow.entity.Task;
import com.uniflow.service.WorkflowService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;

/**
 * 工作流管理控制器
 */
@Api(tags = "工作流管理")
@RestController
@RequestMapping("/api/v1/workflow")
public class WorkflowController {
    
    @Autowired
    private WorkflowService workflowService;
    
    // ==================== 流程定义管理 ====================
    
    @ApiOperation("部署流程定义")
    @PostMapping("/process-definitions/deploy")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<String> deployProcess(
            @ApiParam("流程名称") @RequestParam @NotBlank String name,
            @ApiParam("流程文件") @RequestParam @NotNull MultipartFile file) {
        String deploymentId = workflowService.deployProcess(name, file);
        return Result.success(deploymentId);
    }
    
    @ApiOperation("通过XML部署流程定义")
    @PostMapping("/process-definitions/deploy-xml")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<String> deployProcessByXml(@RequestBody @Valid DeployProcessRequest request) {
        String deploymentId = workflowService.deployProcessByXml(request.getName(), request.getXmlContent());
        return Result.success(deploymentId);
    }
    
    @ApiOperation("分页查询流程定义列表")
    @GetMapping("/process-definitions")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<PageResult<ProcessDefinition>> getProcessDefinitionList(
            @ApiParam("页码") @RequestParam(defaultValue = "1") int pageNum,
            @ApiParam("页大小") @RequestParam(defaultValue = "10") int pageSize,
            @ApiParam("关键词") @RequestParam(required = false) String keyword,
            @ApiParam("分类") @RequestParam(required = false) String category) {
        PageResult<ProcessDefinition> result = workflowService.getProcessDefinitionList(
                pageNum, pageSize, keyword, category);
        return Result.success(result);
    }
    
    @ApiOperation("根据ID查询流程定义详情")
    @GetMapping("/process-definitions/{id}")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<ProcessDefinition> getProcessDefinitionById(
            @ApiParam("流程定义ID") @PathVariable @NotBlank String id) {
        ProcessDefinition definition = workflowService.getProcessDefinitionById(id);
        return Result.success(definition);
    }
    
    @ApiOperation("获取流程定义XML内容")
    @GetMapping("/process-definitions/{id}/xml")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<String> getProcessDefinitionXml(
            @ApiParam("流程定义ID") @PathVariable @NotBlank String id) {
        String xml = workflowService.getProcessDefinitionXml(id);
        return Result.success(xml);
    }
    
    @ApiOperation("删除流程定义")
    @DeleteMapping("/process-definitions/{deploymentId}")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<Void> deleteProcessDefinition(
            @ApiParam("部署ID") @PathVariable @NotBlank String deploymentId,
            @ApiParam("是否级联删除") @RequestParam(defaultValue = "false") boolean cascade) {
        workflowService.deleteProcessDefinition(deploymentId, cascade);
        return Result.success();
    }
    
    @ApiOperation("激活/挂起流程定义")
    @PutMapping("/process-definitions/{id}/status")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<Void> activateOrSuspendProcessDefinition(
            @ApiParam("流程定义ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid ProcessDefinitionStatusRequest request) {
        workflowService.activateOrSuspendProcessDefinition(id, request.isActivate());
        return Result.success();
    }
    
    // ==================== 流程实例管理 ====================
    
    @ApiOperation("启动流程实例")
    @PostMapping("/process-instances/start")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<ProcessInstance> startProcess(@RequestBody @Valid StartProcessRequest request) {
        ProcessInstance instance = workflowService.startProcess(
                request.getProcessDefinitionKey(),
                request.getBusinessKey(),
                request.getVariables(),
                request.getStartUserId());
        return Result.success(instance);
    }
    
    @ApiOperation("分页查询流程实例列表")
    @GetMapping("/process-instances")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<PageResult<ProcessInstance>> getProcessInstanceList(
            @ApiParam("页码") @RequestParam(defaultValue = "1") int pageNum,
            @ApiParam("页大小") @RequestParam(defaultValue = "10") int pageSize,
            @ApiParam("流程定义Key") @RequestParam(required = false) String processDefinitionKey,
            @ApiParam("业务Key") @RequestParam(required = false) String businessKey,
            @ApiParam("启动用户ID") @RequestParam(required = false) String startUserId,
            @ApiParam("是否已结束") @RequestParam(required = false) Boolean finished) {
        PageResult<ProcessInstance> result = workflowService.getProcessInstanceList(
                pageNum, pageSize, processDefinitionKey, businessKey, startUserId, finished);
        return Result.success(result);
    }
    
    @ApiOperation("根据ID查询流程实例详情")
    @GetMapping("/process-instances/{id}")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<ProcessInstance> getProcessInstanceById(
            @ApiParam("流程实例ID") @PathVariable @NotBlank String id) {
        ProcessInstance instance = workflowService.getProcessInstanceById(id);
        return Result.success(instance);
    }
    
    @ApiOperation("删除流程实例")
    @DeleteMapping("/process-instances/{id}")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<Void> deleteProcessInstance(
            @ApiParam("流程实例ID") @PathVariable @NotBlank String id,
            @ApiParam("删除原因") @RequestParam(required = false) String deleteReason) {
        workflowService.deleteProcessInstance(id, deleteReason);
        return Result.success();
    }
    
    @ApiOperation("激活/挂起流程实例")
    @PutMapping("/process-instances/{id}/status")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<Void> activateOrSuspendProcessInstance(
            @ApiParam("流程实例ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid ProcessInstanceStatusRequest request) {
        workflowService.activateOrSuspendProcessInstance(id, request.isActivate());
        return Result.success();
    }
    
    // ==================== 任务管理 ====================
    
    @ApiOperation("分页查询任务列表")
    @GetMapping("/tasks")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<PageResult<Task>> getTaskList(
            @ApiParam("页码") @RequestParam(defaultValue = "1") int pageNum,
            @ApiParam("页大小") @RequestParam(defaultValue = "10") int pageSize,
            @ApiParam("执行人") @RequestParam(required = false) String assignee,
            @ApiParam("流程定义Key") @RequestParam(required = false) String processDefinitionKey,
            @ApiParam("流程实例ID") @RequestParam(required = false) String processInstanceId,
            @ApiParam("任务名称") @RequestParam(required = false) String taskName,
            @ApiParam("是否已完成") @RequestParam(required = false) Boolean finished) {
        PageResult<Task> result = workflowService.getTaskList(
                pageNum, pageSize, assignee, processDefinitionKey, processInstanceId, taskName, finished);
        return Result.success(result);
    }
    
    @ApiOperation("完成任务")
    @PostMapping("/tasks/{id}/complete")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<Void> completeTask(
            @ApiParam("任务ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid CompleteTaskRequest request) {
        workflowService.completeTask(id, request.getVariables(), request.getComment());
        return Result.success();
    }
    
    @ApiOperation("认领任务")
    @PostMapping("/tasks/{id}/claim")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<Void> claimTask(
            @ApiParam("任务ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid ClaimTaskRequest request) {
        workflowService.claimTask(id, request.getUserId());
        return Result.success();
    }
    
    @ApiOperation("委派任务")
    @PostMapping("/tasks/{id}/delegate")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<Void> delegateTask(
            @ApiParam("任务ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid DelegateTaskRequest request) {
        workflowService.delegateTask(id, request.getUserId());
        return Result.success();
    }
    
    @ApiOperation("转办任务")
    @PostMapping("/tasks/{id}/assign")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<Void> assignTask(
            @ApiParam("任务ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid AssignTaskRequest request) {
        workflowService.assignTask(id, request.getUserId());
        return Result.success();
    }
    
    // ==================== 工作流统计和扩展功能 ====================
    
    @ApiOperation("获取工作流统计信息")
    @GetMapping("/statistics")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<Map<String, Object>> getWorkflowStatistics() {
        Map<String, Object> statistics = workflowService.getWorkflowStatistics();
        return Result.success(statistics);
    }
    
    @ApiOperation("获取工作流分类列表")
    @GetMapping("/categories")
    @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
    public Result<List<String>> getWorkflowCategories() {
        List<String> categories = workflowService.getWorkflowCategories();
        return Result.success(categories);
    }
    
    @ApiOperation("验证工作流定义")
    @PostMapping("/validate")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<Map<String, Object>> validateWorkflow(@RequestBody @Valid ValidateWorkflowRequest request) {
        Map<String, Object> result = workflowService.validateWorkflow(request.getNodes(), request.getConnections());
        return Result.success(result);
    }
    
    @ApiOperation("导入工作流")
    @PostMapping("/import")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<String> importWorkflow(
            @ApiParam("工作流文件") @RequestParam @NotNull MultipartFile file) {
        String deploymentId = workflowService.importWorkflow(file);
        return Result.success(deploymentId);
    }
    
    @ApiOperation("复制工作流")
    @PostMapping("/process-definitions/{id}/copy")
    @PreAuthorize("hasRole('ADMIN') or hasAuthority('WORKFLOW_MANAGE')")
    public Result<String> copyWorkflow(
            @ApiParam("流程定义ID") @PathVariable @NotBlank String id,
            @RequestBody @Valid CopyWorkflowRequest request) {
        String newDeploymentId = workflowService.copyWorkflow(id, request.getName());
        return Result.success(newDeploymentId);
    }
    
    // ==================== 请求数据结构 ====================
    
    /**
     * 部署流程请求
     */
    public static class DeployProcessRequest {
        @NotBlank(message = "流程名称不能为空")
        private String name;
        
        @NotBlank(message = "XML内容不能为空")
        private String xmlContent;
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
        
        public String getXmlContent() {
            return xmlContent;
        }
        
        public void setXmlContent(String xmlContent) {
            this.xmlContent = xmlContent;
        }
    }
    
    /**
     * 流程定义状态请求
     */
    public static class ProcessDefinitionStatusRequest {
        @NotNull(message = "激活状态不能为空")
        private Boolean activate;
        
        public Boolean isActivate() {
            return activate;
        }
        
        public void setActivate(Boolean activate) {
            this.activate = activate;
        }
    }
    
    /**
     * 启动流程请求
     */
    public static class StartProcessRequest {
        @NotBlank(message = "流程定义Key不能为空")
        private String processDefinitionKey;
        
        private String businessKey;
        
        private Map<String, Object> variables;
        
        @NotBlank(message = "启动用户ID不能为空")
        private String startUserId;
        
        public String getProcessDefinitionKey() {
            return processDefinitionKey;
        }
        
        public void setProcessDefinitionKey(String processDefinitionKey) {
            this.processDefinitionKey = processDefinitionKey;
        }
        
        public String getBusinessKey() {
            return businessKey;
        }
        
        public void setBusinessKey(String businessKey) {
            this.businessKey = businessKey;
        }
        
        public Map<String, Object> getVariables() {
            return variables;
        }
        
        public void setVariables(Map<String, Object> variables) {
            this.variables = variables;
        }
        
        public String getStartUserId() {
            return startUserId;
        }
        
        public void setStartUserId(String startUserId) {
            this.startUserId = startUserId;
        }
    }
    
    /**
     * 流程实例状态请求
     */
    public static class ProcessInstanceStatusRequest {
        @NotNull(message = "激活状态不能为空")
        private Boolean activate;
        
        public Boolean isActivate() {
            return activate;
        }
        
        public void setActivate(Boolean activate) {
            this.activate = activate;
        }
    }
    
    /**
     * 完成任务请求
     */
    public static class CompleteTaskRequest {
        private Map<String, Object> variables;
        
        private String comment;
        
        public Map<String, Object> getVariables() {
            return variables;
        }
        
        public void setVariables(Map<String, Object> variables) {
            this.variables = variables;
        }
        
        public String getComment() {
            return comment;
        }
        
        public void setComment(String comment) {
            this.comment = comment;
        }
    }
    
    /**
     * 认领任务请求
     */
    public static class ClaimTaskRequest {
        @NotBlank(message = "用户ID不能为空")
        private String userId;
        
        public String getUserId() {
            return userId;
        }
        
        public void setUserId(String userId) {
            this.userId = userId;
        }
    }
    
    /**
     * 委派任务请求
     */
    public static class DelegateTaskRequest {
        @NotBlank(message = "用户ID不能为空")
        private String userId;
        
        public String getUserId() {
            return userId;
        }
        
        public void setUserId(String userId) {
            this.userId = userId;
        }
    }
    
    /**
     * 转办任务请求
     */
    public static class AssignTaskRequest {
        @NotBlank(message = "用户ID不能为空")
        private String userId;
        
        public String getUserId() {
            return userId;
        }
        
        public void setUserId(String userId) {
            this.userId = userId;
        }
    }
    
    /**
     * 验证工作流请求
     */
    public static class ValidateWorkflowRequest {
        private List<Map<String, Object>> nodes;
        private List<Map<String, Object>> connections;
        
        public List<Map<String, Object>> getNodes() {
            return nodes;
        }
        
        public void setNodes(List<Map<String, Object>> nodes) {
            this.nodes = nodes;
        }
        
        public List<Map<String, Object>> getConnections() {
            return connections;
        }
        
        public void setConnections(List<Map<String, Object>> connections) {
            this.connections = connections;
        }
    }
    
    /**
     * 复制工作流请求
     */
    public static class CopyWorkflowRequest {
        @NotBlank(message = "工作流名称不能为空")
        private String name;
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
    }
}